package com.simpou.commons.utils.lang;

import com.simpou.commons.utils.behavior.Condition;
import com.simpou.commons.utils.behavior.Conditions;

import java.util.Collection;


/**
 * Operações úteis em condicionais.
 *
 * @author Jonas Pereira
 * @since 2012-10-17
 * @version 2013-05-31
 */
public class Conditionals {
    /**
     * @param objects Objetos que devem ser não nulos.
     * @return true se nenhume objeto for null.
     */
    public static boolean isNotNull(final Object... objects) {
        for (final Object object : objects) {
            if (object == null) {
                return false;
            }
        }

        return true;
    }

    /**
     * @param array Array.
     * @return true se array for nulo ou vazio.
     */
    public static boolean isEmpty(final Object[] array) {
        return (array == null) || (array.length == 0);
    }

    /**
     * @param array Array.
     * @return true se array for não nulo e não vazio.
     */
    public static boolean isNotEmpty(final Object[] array) {
        return !isEmpty(array);
    }

    /**
     * @param string String.
     * @return true se string for nula ou vazia.
     */
    public static boolean isEmpty(final String string) {
        return (string == null) || (string.length() == 0);
    }

    /**
     * @param string String.
     * @return true se string for não nula e não vazia.
     */
    public static boolean isNotEmpty(final String string) {
        return !isEmpty(string);
    }

    /**
     * @param collection Coleção.
     * @return true se coleção é nula ou vazia.
     */
    public static boolean isEmpty(final Collection<?> collection) {
        return (collection == null) || collection.isEmpty();
    }

    /**
     * @param collection Coleção.
     * @return true se coleção é não nula e não vazia.
     */
    public static boolean isNotEmpty(final Collection<?> collection) {
        return !isEmpty(collection);
    }

    /**
     * @param <T> Tipo do contexto.
     * @param context Objeto alvo de análise da condição.
     * @param condition Condição a ser analisada sobre o contexto.
     * @return true se a condição for satisfeita pelo objeto.
     */
    public static <T> boolean check(final T context, final Condition<T> condition) {
        return condition.check(context);
    }

    /**
     * @param <E> Contexto.
     * @param condition Condição.
     * @return Negativa da condição.
     */
    public static <E> Condition<E> negate(final Condition<E> condition) {
        return new Condition<E>() {
            @Override
            public boolean check(E context) {
                return !condition.check(context);
            }
        };
    }
}
